#include <iostream>
#include <unordered_map>
#include "../Connection.hpp"
#include "Request&&Response.hpp"
#include "../RoomPlayers.hpp"

extern std::unordered_map<std::string, Room *> rooms;
extern std::unordered_map<int, std::string> fd_to_room_number;

class RequestJoinRoom : public Request
{
public:
	RequestJoinRoom() {}

	virtual bool Serialize(std::string *msg)
	{
		// Json::Value root;
		// root["server_type"] = JoinRoom;
		// root["room_number"] = _room_number;
		// Json::FastWriter writer;
		// *msg = writer.write(root);

		return true;
	}
	virtual bool Deserialize(const Json::Value &root)
	{
		_room_number = root["room_number"].asString();
		return true;
	}

	std::string GetRoomNumber() const
	{
		return _room_number;
	}

	// void SetRoomRumber(const std::string& room_number)
	// {
	// 	_room_number = room_number;
	// }

	~RequestJoinRoom() {}

private:
	std::string _room_number;
};

class ResponseJoinRoom : public Response
{
public:
	ResponseJoinRoom() {}

	virtual bool Serialize(std::string *msg)
	{
		Json::Value root;
		root["return"] = _return;
		root["max_member"] = _max_member;
		root["player_id"] = _player_id;
		root["cur_member_number"] = _cur_member_number;
		Json::FastWriter writer;
		*msg = writer.write(root);
		_return = 0;
		return true;
	}

	virtual bool ServerHandler(const RequestJoinRoom *req, Connection *conn)
	{
		if (rooms.find(req->GetRoomNumber()) == rooms.end())
		{
			_return = -1;
			return true;
		}
		if (rooms[req->GetRoomNumber()]->GetMaxMember() == rooms[req->GetRoomNumber()]->GetPlayersNumber().size())
		{
			_return = -2;
			return true;
		}

		_max_member = rooms[req->GetRoomNumber()]->GetMaxMember();
		_player_id = rooms[req->GetRoomNumber()]->AddPlayer(conn);
		_cur_member_number = rooms[req->GetRoomNumber()]->GetPlayersNumber();

		// std::cout << "Join: " << _cur_member_number << std::endl;
		fd_to_room_number[conn->GetFd()] = req->GetRoomNumber();

		std::vector<Player> &players = rooms[fd_to_room_number[conn->GetFd()]]->GetPlayers();
		std::string msg;
		Json::Value root;
		root["server_type"] = JoinRoom;
		root["player_id"] = _player_id;
		Json::FastWriter writer;
		msg = writer.write(root);
		Package(msg, &msg);
		for (int i = 0; i < players.size(); i++)
		{
			if (players[i].Exist())
			{
				Connection *conn_player = players[i].GetConnection();
				// std::cout << "conn_player->GetOutbuffer() " << conn_player->GetOutbuffer() << std::endl;
				if (conn_player != nullptr && conn != conn_player)
				{
					conn_player->GetOutbuffer() += msg;
					// std::cout << "conn_player->GetOutbuffer() " << conn_player->GetOutbuffer() << std::endl;
					conn_player->GetWriter()(conn_player);
				}
			}
		}

		return true;
	}

	// virtual bool ServerHandler(const RequestJoinRoom* req, Connection* conn)
	// {
	//     // RequestJoinRoom* requestjoinreq = (RequestJoinRoom*)req;
	//     if(rooms.find(req->GetRoomNumber()) == rooms.end())
	//     // if(rooms.find(requestjoinreq->GetRoomNumber()) == rooms.end())
	//     {
	//         _return  = -1;
	//         return true;
	//         // return false;
	//     }
	//     if(rooms[req->GetRoomNumber()]->GetMaxMember() == rooms[req->GetRoomNumber()]->GetPlayersNumber().size())
	//     // if(rooms[requestjoinreq->GetRoomNumber()]->GetMaxMember() == rooms[requestjoinreq->GetRoomNumber()]->GetPlayersNumber().size())
	//     {
	//         _return  = -2;
	//         return true;
	//         // return false;
	//     }
	//     // std::cout << *msg << std::endl;

	//     _max_member = rooms[req->GetRoomNumber()]->GetMaxMember();
	//     _player_id = rooms[req->GetRoomNumber()]->AddPlayer(conn);
	// 	_cur_member_number = rooms[req->GetRoomNumber()]->GetPlayersNumber();

	//     // _max_member = rooms[requestjoinreq->GetRoomNumber()]->GetMaxMember();
	//     // _player_id = rooms[requestjoinreq->GetRoomNumber()]->AddPlayer(fd);
	// 	// _cur_member_number = rooms[requestjoinreq->GetRoomNumber()]->GetPlayersNumber();
	// 	std::cout << _cur_member_number << std::endl;
	// 	fd_to_room_number[conn->GetFd()] = req->GetRoomNumber();
	// 	// fd_to_room_number[fd] = requestjoinreq->GetRoomNumber();

	// 	return true;
	// }

	virtual bool Deserialize(const std::string &result)
	{
		// Json::Value root;
		// Json::Reader reader;
		// reader.parse(result, root);
		// _return = root["return"].asInt();
		// if (_return == -1)
		// 	return false;
		// if (_return == -2)
		// 	return false;

		// _max_member = root["max_member"].asInt();
		// _player_id = root["player_id"].asInt();

		return true;
	}

	int GetMaxMember()
	{
		return _max_member;
	}

	int GetPlayerId()
	{
		return _player_id;
	}

	virtual ~ResponseJoinRoom() {}

private:
	int _return = 0;
	int _max_member = 0;
	int _player_id = 0;
	std::string _cur_member_number;
};
